package com.sneakxy.mybase4j.platform.controller;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.sneakxy.mybase4j.base.bean.ValidAdd;
import com.sneakxy.mybase4j.base.bean.ValidEdit;
import com.sneakxy.mybase4j.base.controller.BaseController;
import com.sneakxy.mybase4j.platform.beans.Account;
import com.sneakxy.mybase4j.platform.beans.AccountRole;
import com.sneakxy.mybase4j.platform.beans.Role;
import com.sneakxy.mybase4j.platform.service.IAccountRoleService;
import com.sneakxy.mybase4j.platform.service.IAccountService;
import com.sneakxy.mybase4j.platform.service.IRoleService;
import com.sneakxy.mybase4j.util.BeanHelper;
import com.sneakxy.mybase4j.util.DataGrid;
import com.sneakxy.mybase4j.util.PageSearch;
import com.sneakxy.mybase4j.util.Response;
import com.sneakxy.mybatis.commons.repository.query.domain.CriteriaBuilder;

/**
 * 账户管理
 * @author 潜行的青衣
 * @see
 */
@RestController
@RequestMapping("/api/account/")
public class AccountController extends BaseController {

	@Resource
	private IAccountService accountService;
	
	@Resource
	private IRoleService roleService;
	
	@Resource
	private IAccountRoleService accountRoleService;
	
	@Resource
	private PasswordEncoder passwordEncoder;
	
	@RequiresPermissions("sys:account:manager")
	@RequestMapping("datagrid")
	public DataGrid<Account> datagrid(PageSearch search) {
		if(StringUtils.isBlank(search.getSortName())) {
			search.setSortName("createtime");
		}
		return new DataGrid<Account>(accountService.findBySearch(search.getSearchText(), search.toPageable()));
	}
	
	@RequiresPermissions("sys:account:manager:add")
	@RequestMapping("add")
	public Response add(@Validated(ValidAdd.class) Account account, BindingResult result) {
		if(result.hasErrors()) {
			return this.getFieldErrorsResponse(result);
		}
		
		//去空格
		BeanHelper.trimToNull(account);
		
		if(!this.validate(account.getAccount())) {
			return new Response(false, 1);
		}
		
		account.setPassword(this.passwordEncoder.encode(account.getPassword()));
		
		account = this.accountService.save(account);
		return new Response(true, account);
	}
	
	@RequiresPermissions("sys:account:manager:edit")
	@RequestMapping("edit")
	public Response edit(@Validated(ValidEdit.class) Account account, BindingResult result) {
		if(result.hasErrors()) {
			return this.getFieldErrorsResponse(result);
		}
		
		//去空格
		BeanHelper.trimToNull(account);
		
		if(!this.validate(account.getId(), account.getAccount())) {
			return new Response(false, 1);
		}
		
		Account old = this.accountService.findOne(account.getId());
		
		if(StringUtils.isNotBlank(account.getPassword())) {
			account.setPassword(this.passwordEncoder.encode(account.getPassword()));
		} else {
			account.setPassword(old.getPassword());
		}
		account.setOwner(old.getOwner());
		account.setCreatetime(old.getCreatetime());
		
		account = this.accountService.save(account);
		return new Response(true, account);
	}
	
	@RequiresPermissions("sys:account:manager:add")
	@RequestMapping("validateAccountAdd")
	public Boolean validate(String account) {
		CriteriaBuilder<Account> builder = new CriteriaBuilder<Account>(Account.class);
		builder.andEq("account", account);
		return this.accountService.count(builder.build()) == 0;
	}
	
	@RequiresPermissions("sys:account:manager:edit")
	@RequestMapping("validateAccountEdit")
	public Boolean validate(String id, String account) {
		CriteriaBuilder<Account> builder = new CriteriaBuilder<Account>(Account.class);
		builder.andEq("account", account);
		builder.andNotEq("id", id);
		return this.accountService.count(builder.build()) == 0;
	}

	@RequiresPermissions("sys:account:manager:remove")
	@RequestMapping("remove")
	public Response remove(String[] ids) {
		if(ids != null) {
			for(String id:ids) {
				this.accountRoleService.deleteByAccountId(id);
				this.accountService.delete(id);
			}
		}
		return new Response(true);
	}
	
	@RequiresPermissions("sys:account:manager:role")
	@RequestMapping("roleData")
	public Response roleData(String id) {
		List<String> selectors = this.accountRoleService.findRoles(id);
		List<Role> roles = this.roleService.findAll(new Sort(new Order(Direction.ASC, "sort")));
		Map<String, Object> result  = new LinkedHashMap<String, Object>();
		result.put("roles", roles);
		result.put("selectors", selectors);
		return new Response(result);
	}
	
	@RequiresPermissions("sys:account:manager:role")
	@RequestMapping("role")
	public Response role(String id, String[] roleIds) {
		this.accountRoleService.deleteByAccountId(id);
		if(roleIds != null) {
			List<AccountRole> entities = new ArrayList<AccountRole>();
			for(String roleId: roleIds) {
				entities.add(new AccountRole(id, roleId, true));
			}
			this.accountRoleService.save(entities);
		}
		return new Response(true);
	}
	
}
